package com.gbiac.modules.monitor.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gbiac.modules.monitor.entity.Rule;
import com.gbiac.modules.monitor.mapper.RuleMapper;
import com.gbiac.modules.monitor.model.dto.AttendanceDTO;
import com.gbiac.modules.monitor.param.RuleSaveParam;
import com.gbiac.modules.monitor.service.IRuleService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.gbiac.modules.monitor.constant.MonitorConstant;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 规则配置
 * @Author: jeecg-boot
 * @Date:   2024-11-30
 * @Version: V1.0
 */
@Service
public class RuleServiceImpl extends ServiceImpl<RuleMapper, Rule> implements IRuleService {

    @Resource
    private RuleMapper ruleMapper;
    @Resource
    private RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(RuleSaveParam param) {
        List<Rule> ruleList = param.getRuleList();
        if (CollectionUtils.isEmpty(ruleList)) {
            return;
        }
        for (Rule rule : ruleList) {
            if (StringUtils.isEmpty(rule.getRuleKey())) {
                throw new JeecgBootException("规则 key 不能为空");
            }
            Rule dbRule = getOne(new LambdaQueryWrapper<Rule>().eq(Rule::getRuleKey, rule.getRuleKey()).orderByDesc(Rule::getVer), false);
            if (dbRule == null) {
                rule.setVer(1);
                save(rule);

                redisUtil.set(MonitorConstant.REDIS_AI_PREFIX_RULE_SETS+":"+rule.getRuleKey(),rule.getVal());
                continue;
            }
            // 判断 val 是否有变化，没有变化则不需要增加新记录
            if ((StringUtils.isBlank(rule.getVal()) && StringUtils.isNotBlank(dbRule.getVal()))
                    || !rule.getVal().equals(dbRule.getVal())
            ) {
                // 新增规则，版本号 +1
                rule.setVer(dbRule.getVer() + 1);
                save(rule);
                redisUtil.set(MonitorConstant.REDIS_AI_PREFIX_RULE_SETS+":"+rule.getRuleKey(),rule.getVal());
            }
        }
    }

    @Override
    public String getRuleVal(String key) {
        Rule rule = getOne(new LambdaQueryWrapper<Rule>().eq(Rule::getRuleKey, key).orderByDesc(Rule::getVer), false);
        if (rule == null) {
            return "";
        }
        return rule.getVal();
    }

    @Override
    public List<Rule> listLastRule(Wrapper<Rule> queryWrapper) {
        return ruleMapper.listLastRule(queryWrapper);
    }

    @Override
    public AttendanceDTO queryAttendanceByOrg(String orgCode) {
        // 计算总时长
        // 考勤规则列表
        List<Rule> attendanceRuleList = listLastRule(new LambdaQueryWrapper<Rule>().likeRight(Rule::getRuleKey, Rule.Key.Attendance.ATTENDANCE));

        if (CollectionUtils.isEmpty(attendanceRuleList)) {
            throw new JeecgBootException("未配置考勤规则");
        }
        // 白班
        Rule dayStartTime, dayEndTime;
        // 夜班1
        Rule night1StartTime, night1EndTime;

        // 夜班2
        Rule night2StartTime, night2EndTime;
        if ("A01A01".equals(orgCode)) {
            // 管制部
            Map<String, Rule> departAttendanceRule = attendanceRuleList.stream()
                    .filter((item) -> item.getRuleKey().startsWith(Rule.Key.Attendance.Control.CONTROL))
                    .collect(Collectors.toMap(Rule::getRuleKey, v -> v, (k1, k2) -> k1));
            // 白班
            dayStartTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Day.START_TIME);
            dayEndTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Day.END_TIME);
            // 夜班1
            night1StartTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Night1.START_TIME);
            night1EndTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Night1.END_TIME);

            // 夜班2
            night2StartTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Night2.START_TIME);
            night2EndTime = departAttendanceRule.get(Rule.Key.Attendance.Control.Night2.END_TIME);
            if (dayStartTime == null || dayEndTime == null || night1StartTime == null || night1EndTime == null || night2StartTime == null || night2EndTime == null) {
                throw new JeecgBootException("管制部考勤规则未配置");
            }
        } else if ("A01A02".equals(orgCode)) {
            // 运行部
            Map<String, Rule> departAttendanceRule = attendanceRuleList.stream()
                    .filter((item) -> item.getRuleKey().startsWith(Rule.Key.Attendance.Operation.OPERATION))
                    .collect(Collectors.toMap(Rule::getRuleKey, v -> v, (k1, k2) -> k1));
            // 白班
            dayStartTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Day.START_TIME);
            dayEndTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Day.END_TIME);

            // 夜班1
            night1StartTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Night1.START_TIME);
            night1EndTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Night1.END_TIME);

            // 夜班2
            night2StartTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Night2.START_TIME);
            night2EndTime = departAttendanceRule.get(Rule.Key.Attendance.Operation.Night2.END_TIME);
            if (dayStartTime == null || dayEndTime == null || night1StartTime == null || night1EndTime == null || night2StartTime == null || night2EndTime == null) {
                throw new JeecgBootException("运行部考勤规则未配置");
            }
        } else {
            throw new JeecgBootException("仅支持管制部和运行部人员上岗");
        }
        AttendanceDTO attendanceDTO = new AttendanceDTO();
        attendanceDTO.setDayStartTime(dayStartTime);
        attendanceDTO.setDayEndTime(dayEndTime);
        attendanceDTO.setNight1StartTime(night1StartTime);
        attendanceDTO.setNight1EndTime(night1EndTime);
        attendanceDTO.setNight2StartTime(night2StartTime);
        attendanceDTO.setNight2EndTime(night2EndTime);
        return attendanceDTO;
    }

}
